Skip to content

Improve agent planning and observability#380

Merged
michaelmwu merged 3 commits into
mainfrom
michaelmwu/review-agent-smartness
Jul 9, 2026
Merged

Improve agent planning and observability#380
michaelmwu merged 3 commits into
mainfrom
michaelmwu/review-agent-smartness

Conversation

@michaelmwu

@michaelmwu michaelmwu commented Jul 9, 2026

Copy link
Copy Markdown
Member

Summary

  • Add a shared, proposal-only structured planner used by the production Discord gateway and live eval contract.
  • Select the actual fast/strong model tier before planning, then enforce allowlisted, bounded planner arguments before policy and confirmation.
  • Improve role-aware agent discovery and record model, action, and tool-outcome metadata in the dashboard.
  • Add configuration, documentation, rebuilt dashboard assets, and regression coverage.

Why

The prior live planner eval measured a richer planner than the production gateway used. Production now consumes the same structured planning contract while preserving deterministic and legacy-normalizer fallbacks for unavailable providers.

Validation

  • uv run --locked pytest -q tests/unit/test_agent_planner.py tests/unit/test_agent_gateway.py tests/unit/test_agent_evals.py tests/unit/test_agent_cog.py tests/unit/test_backend_api.py tests/unit/test_worker_config.py
  • uv run --locked python scripts/agent_eval.py --suite canonical --model primary --no-env-file --json — 25 passed, 0 failed, 1 accepted known failure
  • ./scripts/lint.sh
  • ./scripts/pyrefly.sh
  • bun run typecheck && bun run lint && bun run test && bun run build in apps/admin_dashboard

A full Python-suite run reached 1,882 passing tests before an order-dependent PyO3/Pydantic crash in pre-existing expected-validation tests; each affected test passes in isolation.


Note

Medium Risk
Changes the live agent planning entry point and reporting/audit semantics for Discord workflows; mitigated by documented fallbacks and bounded planner timeouts, but misconfiguration could affect routing or dashboard metrics.

Overview
Aligns the production Discord agent gateway with the shared proposal-only structured planner by injecting OpenAICompatibleAgentPlanner.from_settings into AgentOrchestrator, alongside the existing intent normalizer fallback path.

Adds AGENT_STRUCTURED_PLANNER_ENABLED and AGENT_STRUCTURED_PLANNER_TIMEOUT_SECONDS (documented to stay under AGENT_API_TIMEOUT_SECONDS) and updates ENVIRONMENT.md to describe structured planning first, with deterministic parsing and legacy normalization as fallbacks.

Observability: agent request and confirmation audit metadata now records model tier/source, planned action names, and per-tool outcomes. The dashboard agent report aggregates model, action, and tool outcome counts, limits summary totals to agent.request events, and unions recent agent.confirmation rows into the report query. The admin UI surfaces the new breakdown dimensions. Unsupported-user copy is shortened to "I could not map that to a supported workflow."

Reviewed by Cursor Bugbot for commit 20725b7. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features

    • Added structured agent planning with validation, clarification prompts, and confirmation for proposed write actions.
    • Expanded agent capabilities previews based on authorized workflows.
    • Dashboard request reports now include model, action, and tool-outcome breakdowns.
    • Added richer audit details for planning and tool execution.
  • Documentation

    • Updated configuration and agent workflow documentation for structured planning and authorization behavior.
  • Bug Fixes

    • Improved handling of unsupported requests and incomplete or invalid tool proposals.

@cursor

cursor Bot commented Jul 9, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_726ee705-83fe-4512-b2fc-d095ac6824ac)

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The agent gateway now supports structured model proposals with shared parsing, bounded tool validation, policy authorization, confirmation handling, policy-derived capability messaging, and expanded audit/dashboard breakdowns.

Changes

Structured agent planning

Layer / File(s) Summary
Planner contract and provider integration
packages/shared/src/five08/agent/planner.py, packages/shared/src/five08/agent/evals.py, packages/shared/src/five08/agent/__init__.py, apps/worker/..., docs/..., ENVIRONMENT.md, tests/unit/test_agent_planner.py
Adds typed planner drafts, OpenAI-compatible planning, prompt/parsing helpers, configuration defaults, shared exports, evaluation reuse, and planner tests.
Planner orchestration and action gates
packages/shared/src/five08/agent/orchestrator.py, packages/shared/src/five08/agent/tools.py, apps/api/..., apps/discord_bot/README.md, tests/unit/test_agent_gateway.py
Routes requests through structured planning with deterministic fallback, validates bounded multi-action proposals, authorizes actions, and supports confirmation responses.
Policy-based capability messaging
apps/discord_bot/src/five08/discord_bot/cogs/agent.py, apps/discord_bot/README.md, apps/api/..., tests/unit/test_agent_cog.py
Derives displayed capabilities from policy scopes and updates workflow clarification messages and tests.
Audit metadata and request breakdowns
apps/api/..., apps/admin_dashboard/src/main.tsx, apps/api/src/five08/backend/static/dashboard/*, tests/unit/test_backend_api.py
Adds model, action, and tool-outcome audit aggregation and displays the new request-mix dimensions in the dashboard.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DiscordBot
  participant AgentOrchestrator
  participant StructuredPlanner
  participant ToolRegistry
  participant PolicyEngine
  participant AuditReporter
  DiscordBot->>AgentOrchestrator: submit agent request
  AgentOrchestrator->>StructuredPlanner: generate typed proposal
  StructuredPlanner-->>AgentOrchestrator: return draft actions
  AgentOrchestrator->>ToolRegistry: validate tool names and arguments
  ToolRegistry-->>AgentOrchestrator: return validated actions
  AgentOrchestrator->>PolicyEngine: authorize actions
  PolicyEngine-->>AgentOrchestrator: return execution or confirmation decision
  AgentOrchestrator->>AuditReporter: record model, actions, and outcomes
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the main changes to agent planning and observability.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch michaelmwu/review-agent-smartness

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cursor

cursor Bot commented Jul 9, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_a894cede-e07a-4113-84dd-0a364b332db5)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6028b9a7b6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +115 to +119
resolved_member_agreement = self._plan_member_agreement_from_crm(
text,
context,
planner="deterministic_regex",
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve task intent before resolving member agreements

When an admin asks something like Create a task to send member agreement to Caleb, this new pre-parse resolver matches the trailing member agreement ... to Caleb phrase before _parse_action sees the create a task intent, so the agent plans a DocuSeal member-agreement submission instead of creating a task. Before this change, member-agreement CRM resolution only ran after the deterministic task parser missed; keep that ordering or explicitly exclude task-creation requests to avoid turning task requests into external agreement sends.

Useful? React with 👍 / 👎.

"github_issue.search_issues": frozenset({"query", "repository", "state", "limit"}),
"github_issue.create_issue": frozenset({"title", "repository", "body", "labels"}),
"crm_read.search_contacts": frozenset({"query", "limit"}),
"crm_write.update_contact": frozenset({"contact_id", "updates"}),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Constrain CRM update fields from planner

With the structured planner enabled, allowing an arbitrary updates object means a model-proposed crm_write.update_contact can pass any CRM attribute through validation; the executor later applies those keys via contact.set(**updates). For admin requests that the model maps to this tool, this expands the previous deterministic onboarding-state-only behavior into arbitrary CRM mutation after confirmation, so the planner gate should enforce a nested allowlist such as cOnboardingState before accepting the draft.

Useful? React with 👍 / 👎.

Comment thread apps/worker/src/five08/worker/config.py Outdated
Comment on lines +64 to +65
agent_structured_planner_enabled: bool = True
agent_structured_planner_timeout_seconds: float = 8.0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add sample env entries for the new planner settings

These new env-backed settings are documented, but .env.example still only lists the older agent normalizer variables. AGENTS.md says to “Update docs and .env.example when introducing new config,” and without sample entries operators cloning or upgrading from the example env won’t see how to disable the structured planner or tune its timeout.

Useful? React with 👍 / 👎.

Comment on lines +3047 to +3051
for outcome in metadata.get("tool_outcomes") or []:
if not isinstance(outcome, dict):
continue
tool_name = str(outcome.get("tool_name") or "unknown")
status_label = str(outcome.get("status") or "unknown")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include confirmation events in tool outcome counts

This new Tool outcome breakdown is computed from the rows returned by _dashboard_agent_request_report, whose SQL still filters to action = 'agent.request'. Confirmed writes record their actual execution results under agent.confirmation, so most write tools (which require confirmation) will be omitted from these counts and the dashboard will under-report or show zero outcomes for the executions operators need to inspect.

Useful? React with 👍 / 👎.

- outline_write.invite_user: email string, or contact_id/contact_query for a CRM contact.
- account_write.create_user_accounts: contact_id string or contact_query string, mailbox_username string.
- memory_read.get_user_facts: optional user_id string.
- memory_read.get_project_facts: optional project_id string.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid exposing project memory reads without project context

The production prompt now tells the model it can draft memory_read.get_project_facts, but the Discord agent context does not populate a trusted project_id, and the tool later rejects both missing project context and arbitrary user-supplied project IDs. For project-memory questions routed through the structured planner, this will pass planning/policy and then fail execution instead of asking for a supported project context or declining the workflow.

Useful? React with 👍 / 👎.

Comment on lines +568 to +570
if {"project:read", "task:create"} & scopes:
capabilities.append(
"- Tasks: search a project, create tasks, and update your own tasks."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require write scopes before advertising task writes

For an Engineer role, PolicyEngine grants project:read but not task:create or task:update_own; this intersection still adds the Tasks capability and says the agent can create and update tasks, even though those requests will be denied. Split task read/write capability text or require the matching write scopes before advertising task creation and updates.

Useful? React with 👍 / 👎.

Comment on lines +70 to +74
"source_type",
"source_ref",
"source_excerpt",
"verification_status",
"confidence",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep memory provenance server-derived

For structured-planner memory writes, these allowlisted fields let the model set provenance and trust metadata that _remember_memory_fact later persists verbatim. A mistaken or prompt-injected plan can create a remembered fact with forged source_ref or elevated verification_status/confidence after normal confirmation, so these metadata fields should be derived by the backend rather than accepted from planner output.

Useful? React with 👍 / 👎.

Comment thread apps/worker/src/five08/worker/config.py Outdated
agent_planner_model: str = "accounts/fireworks/models/kimi-k2p6"
agent_fallback_model: str = "gpt-4.1-mini"
agent_structured_planner_enabled: bool = True
agent_structured_planner_timeout_seconds: float = 8.0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Leave headroom between planner and bot timeouts

With a model provider configured, the backend may spend the full 8 seconds in the structured planner before falling back to deterministic parsing, but the Discord bot's backend request timeout is also 8 seconds. In slow-provider cases the bot can time out and report a gateway failure even though the backend would otherwise recover, so set the planner timeout below the bot/API timeout or raise the outer request timeout.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/shared/src/five08/agent/evals.py (1)

974-987: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Fallback loses the brace-extraction step, can crash on recoverable output.

parse_planner_draft itself extracts the JSON object between the first { and last } before parsing (planner.py lines 241-253). If that extraction succeeds but Pydantic validation then fails (ValidationError, e.g. an unrecognized legacy status label), this except block re-parses the original raw_output with plain json.loads instead of reusing the extracted substring. For provider output that needed extraction (e.g. wrapped in markdown fences or surrounding prose), this second json.loads(raw_output) call raises a new, uncaught JSONDecodeError — since it's raised from inside the except clause, it is not caught by that same handler and propagates to the caller. The eval harness will crash for exactly the recoverable-but-nonstandard outputs this fallback was designed to handle.

🐛 Proposed fix — reuse the extracted substring
 def _parse_live_planner_json(raw_output: str) -> LivePlannerDraft:
     try:
         return LivePlannerDraft.model_validate(
             parse_planner_draft(raw_output).model_dump(mode="python")
         )
     except (ValidationError, ValueError, json.JSONDecodeError):
-        payload = json.loads(raw_output)
+        value = raw_output.strip()
+        try:
+            payload = json.loads(value)
+        except json.JSONDecodeError:
+            start = value.find("{")
+            end = value.rfind("}")
+            if start < 0 or end <= start:
+                raise
+            payload = json.loads(value[start : end + 1])
         normalized = dict(payload)

Consider exporting the extraction step from planner.py as a small reusable helper so both call sites stay in sync.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared/src/five08/agent/evals.py` around lines 974 - 987,
_parse_live_planner_json should reuse the brace-extracted JSON when fallback
validation fails instead of calling json.loads on the original raw_output.
Extract and export a shared helper from planner.py, then use it in both
parse_planner_draft and _parse_live_planner_json so wrapped or fenced output
remains parseable during fallback normalization.
🧹 Nitpick comments (1)
packages/shared/src/five08/agent/planner.py (1)

170-211: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the duplicated retry-POST block.

The retry-without-response_format path (lines 178-186 and 193-202) duplicates the URL, headers, json, timeout, and verify arguments almost verbatim. Extracting a small _post_completion(url, headers, payload) helper would remove the duplication and prevent future edits (e.g., adding a header) from being applied to only one of the two call sites.

♻️ Proposed refactor
+    def _post(self, base_url: str, api_key: str, payload: dict[str, Any]) -> requests.Response:
+        return requests.post(
+            f"{base_url.rstrip('/')}/chat/completions",
+            headers={
+                "Authorization": f"Bearer {api_key}",
+                "Content-Type": "application/json",
+            },
+            json=payload,
+            timeout=self.timeout_seconds,
+            verify=default_ca_bundle_path(),
+        )
+
     def plan(self, *, message, context, runtime_config, model_tier):
         ...
-        response = requests.post(
-            f"{base_url.rstrip('/')}/chat/completions",
-            headers={...},
-            json=payload,
-            timeout=self.timeout_seconds,
-            verify=default_ca_bundle_path(),
-        )
+        response = self._post(base_url, api_key, payload)
         if (
             _should_retry_without_response_format(response)
             and "response_format" in payload
         ):
             payload.pop("response_format", None)
-            response = requests.post(
-                f"{base_url.rstrip('/')}/chat/completions",
-                headers={...},
-                json=payload,
-                timeout=self.timeout_seconds,
-                verify=default_ca_bundle_path(),
-            )
+            response = self._post(base_url, api_key, payload)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared/src/five08/agent/planner.py` around lines 170 - 211, Extract
the duplicated completion POST logic into a small helper such as
_post_completion, accepting the URL, headers, and payload while applying the
shared timeout and certificate verification settings. Update both the initial
request and the retry in the planner completion flow to call this helper,
preserving the existing response_format removal and retry behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/worker/src/five08/worker/config.py`:
- Around line 64-65: Update agent_structured_planner_timeout_seconds in the
configuration model to use the same positive-value validation as the other
timeout fields, defining it with Field(default=8.0, gt=0) and ensuring the
required Field import is available.

---

Outside diff comments:
In `@packages/shared/src/five08/agent/evals.py`:
- Around line 974-987: _parse_live_planner_json should reuse the brace-extracted
JSON when fallback validation fails instead of calling json.loads on the
original raw_output. Extract and export a shared helper from planner.py, then
use it in both parse_planner_draft and _parse_live_planner_json so wrapped or
fenced output remains parseable during fallback normalization.

---

Nitpick comments:
In `@packages/shared/src/five08/agent/planner.py`:
- Around line 170-211: Extract the duplicated completion POST logic into a small
helper such as _post_completion, accepting the URL, headers, and payload while
applying the shared timeout and certificate verification settings. Update both
the initial request and the retry in the planner completion flow to call this
helper, preserving the existing response_format removal and retry behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 36dada46-8516-45fb-baff-8b1d1038438e

📥 Commits

Reviewing files that changed from the base of the PR and between c3bcbf3 and 6028b9a.

📒 Files selected for processing (20)
  • ENVIRONMENT.md
  • apps/admin_dashboard/src/main.tsx
  • apps/api/src/five08/backend/api.py
  • apps/api/src/five08/backend/static/dashboard/.vite/manifest.json
  • apps/api/src/five08/backend/static/dashboard/assets/index-DCDV0WK0.js
  • apps/api/src/five08/backend/static/dashboard/index.html
  • apps/discord_bot/README.md
  • apps/discord_bot/src/five08/discord_bot/cogs/agent.py
  • apps/worker/src/five08/worker/config.py
  • docs/configuration.md
  • docs/discord-agent-eval-harness.md
  • packages/shared/src/five08/agent/__init__.py
  • packages/shared/src/five08/agent/evals.py
  • packages/shared/src/five08/agent/orchestrator.py
  • packages/shared/src/five08/agent/planner.py
  • packages/shared/src/five08/agent/tools.py
  • tests/unit/test_agent_cog.py
  • tests/unit/test_agent_gateway.py
  • tests/unit/test_agent_planner.py
  • tests/unit/test_backend_api.py

Comment thread apps/worker/src/five08/worker/config.py Outdated
Comment on lines +64 to +65
agent_structured_planner_enabled: bool = True
agent_structured_planner_timeout_seconds: float = 8.0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add gt=0 validation to agent_structured_planner_timeout_seconds.

Other timeout fields in this class enforce positivity with Field(default=X, gt=0) (e.g., job_lead_classifier_timeout_seconds at line 79, intake_resume_fetch_timeout_seconds at line 112). The new field uses a plain float = 8.0 default, allowing zero or negative values that could cause the planner HTTP call to fail immediately or behave unexpectedly.

🛡️ Proposed fix
-    agent_structured_planner_timeout_seconds: float = 8.0
+    agent_structured_planner_timeout_seconds: float = Field(default=8.0, gt=0)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
agent_structured_planner_enabled: bool = True
agent_structured_planner_timeout_seconds: float = 8.0
agent_structured_planner_enabled: bool = True
agent_structured_planner_timeout_seconds: float = Field(default=8.0, gt=0)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/worker/src/five08/worker/config.py` around lines 64 - 65, Update
agent_structured_planner_timeout_seconds in the configuration model to use the
same positive-value validation as the other timeout fields, defining it with
Field(default=8.0, gt=0) and ensuring the required Field import is available.

@cursor

cursor Bot commented Jul 9, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_0a7f6666-632a-464f-820a-455a94f12ad6)

@michaelmwu
michaelmwu added this pull request to the merge queue Jul 9, 2026
Merged via the queue into main with commit 19c4a7d Jul 9, 2026
13 checks passed
@michaelmwu
michaelmwu deleted the michaelmwu/review-agent-smartness branch July 9, 2026 23:49

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 20725b7c24

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +472 to +473
if re.search(r"\bcreate\s+(?:a\s+)?task\b", text, re.IGNORECASE):
return None

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve non-task create intents before agreement resolution

Fresh evidence beyond the earlier task case: this exclusion only protects create task, but plan() still calls the CRM member-agreement resolver before _parse_action, so requests like Create a GitHub issue to send member agreement to Caleb are intercepted as DocuSeal agreement submissions (or denied for engineers without CRM scopes) instead of following the deterministic GitHub-issue path. Exclude all other supported create/update workflows here, or move this resolver back after deterministic parsing misses.

Useful? React with 👍 / 👎.

Comment on lines +235 to +239
"contract_version": PLANNER_CONTRACT_VERSION,
"message": message,
"untrusted_context": render_untrusted_context(context.context_snippets),
"thread": thread or [],
"runtime_config": {"github_default_repo": default_repo},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include current date before planning due dates

When the structured planner handles task requests with relative dates like “tomorrow” or “next Friday”, this payload gives the model the message and context but no trusted current date, while the planner contract asks for due_date as YYYY-MM-DD. That makes the planner produce stale/wrong ISO dates or non-ISO strings that _optional_date later drops, so confirmations can create tasks with incorrect or missing due dates compared with the deterministic parser’s server-date resolution.

Useful? React with 👍 / 👎.

Comment on lines +1599 to +1603
if tool_name == "memory_write.remember_fact":
if not _non_empty_arg(args, "key") or not isinstance(
args.get("value_json"), dict
):
return "What fact should I remember?"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject project memory writes without context

For structured-planner memory writes, a draft with scope_type: "project" only needs key and value_json to pass this clarification gate. Discord agent contexts do not currently populate a trusted project_id, so a Project Manager request like “remember this for this project” can be frozen and confirmed, then fail during execution when _trusted_project_scope_id raises project_id is required in trusted context; mirror the project-read context check before presenting confirmation.

Useful? React with 👍 / 👎.

Comment on lines +207 to +211
if draft.status == "needs_clarification":
question = draft.clarification_question or "What should I do next?"
return AgentResponse(
status="needs_clarification",
message=question,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Try deterministic fallback before planner clarifications

When the structured planner returns needs_clarification, production returns that question immediately, but the live eval path still falls back to the deterministic parser for parseable task searches. With the planner enabled, a model response like the eval-covered Who should I look up? for Show tasks for project Atlas matching onboarding will pass live eval via fallback while production asks a clarification instead of executing the deterministic search, masking planner regressions.

Useful? React with 👍 / 👎.

AgentToolAction(
tool_name=draft_action.tool_name,
arguments=draft_action.arguments,
summary=draft_action.summary,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Derive confirmation summaries from validated actions

For live-model plans this copies the model-supplied summary directly into the frozen plan, and the Discord confirmation text renders human_summary rather than a deterministic view of the tool name and arguments. If the model is confused or influenced by untrusted context, an admin can be asked to confirm a benign-looking summary for a different validated write action, weakening the human confirmation gate; generate the summary from the validated action/arguments instead.

Useful? React with 👍 / 👎.

clarification_question=clarification,
)
return self._response_for_actions(
actions=actions,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject decomposed account-provisioning write plans

This accepts every allowlisted model action as one confirmation plan, so if the planner decomposes “create 508 accounts” into standalone mail_write.create_mailbox, sso_write.create_user, and outline_write.invite_user instead of the composite account_write.create_user_accounts, confirmation executes the standalone tools without the composite preflight/CRM email update semantics and continues after failures. Enforce the composite account tool or reject dependent multi-write planner drafts before confirmation.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant